package mlc.applet;

import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.KeyEvent;

import mlc.Constants;
import mlc.Direction;
import mlc.om.Planet;
import mlc.om.Player;
import mlc.om.Vehicle;

public class MLCApplet extends Applet implements Runnable
{
    //Applet attribute
	private static final long serialVersionUID = 1L;
	private Thread thread=null;
    private Image bufferImage;
    private Graphics bufferGraphics;
    private KeyboardManager keyboardManager;
    private MouseManager mouseManager;
    private Painter painter;
    private boolean paused = true;
    
    //MLC attribute    
    private Planet planet;
    private Player player;
    private Vehicle vehicle;

    public void init(){
		planet = new Planet();
    	player = new Player();
    	vehicle = player.getVehicle(); 
    }

    public void update(Graphics g) {
    	//Initialize buffer
    	if (bufferImage == null)
    	{
    		bufferImage = createImage(this.getSize().width, this.getSize().height);
    		bufferGraphics = bufferImage.getGraphics();
    	}

    	//Clear screen in background
    	bufferGraphics.setColor(getBackground());
    	bufferGraphics.fillRect(0, 0, this.getSize().width, this.getSize().height);

    	//Draw elements in background
    	bufferGraphics.setColor(getForeground());
    	paint(bufferGraphics);

    	//Draw image on the screen
    	g.drawImage(bufferImage, 0, 0, this);
    }

    public void paint(Graphics g)
    {
    	Graphics2D g2d = (Graphics2D)g;
    	
    	//Calculate current sky height to define blue darkness
    	//Calculate ground start width delta on applet graphics
    	//Fill background with blue gradient color
    	//Calculate ground start height delta on applet graphics
    	//Fill ground background section with black color    
    	//With visible sky draw width relative structures
    	//Calculate ground rows to be painted
    	//Draw visible ground rows with associated ores
    	//Draw fuel and hull indicators
    	//Draw money and points
    	//Draw the vehicle
    	painter.paintBackground(g2d);
    	//painter.paintCrossOfPositionAndSpeed(g2d);
    	painter.paintVehicleAsSquare(g2d);
    	painter.paintGameStatus(g2d);
    }

    public void run()
    {
    	//Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
        while(true)            
        {
        	if(!paused){
	        	//Compute all loop data
	        	//Verify used constants input
	        	boolean isEngineHorizzontalWorking = verifyInputs();
	        	//Verify if vehicle can fall
	        		//Apply gravity to vertical speed till max speed reached	        		
	        		vehicle.applyGravitySpeed();
	        	//Apply friction to horizontal speed till zero
	        		if(!isEngineHorizzontalWorking)
	        			vehicle.applyHorizzontalFriction();
	        	//Calculate vehicle next position
	        		double nextX = vehicle.getGlobalPosition().getX() + vehicle.getSpeedX()*0.1;
	        		if(nextX > getSize().getWidth()){
	        			nextX = getSize().getWidth();
	        			vehicle.clearSpeed(Direction.RIGHT);
	        		}
	        		if(nextX < 0){
	        			nextX = 0;
	        			vehicle.clearSpeed(Direction.LEFT);
	        		}
	        		double nextY = vehicle.getGlobalPosition().getY() + vehicle.getSpeedY()*0.1;
	        		if(nextY > getSize().getHeight()){
	        			nextY = getSize().getHeight();
	        			vehicle.clearSpeed(Direction.DOWN);
	        		}
	        		if(nextY < Constants.squarePixelsSize){
	        			nextY = Constants.squarePixelsSize;
	        			vehicle.clearSpeed(Direction.UP);
	        		}
	        		vehicle.setGlobalPosition(new Point((int)nextX, (int)nextY));
	        	//Verify any collision
	        		//For collision manage it correctly
	        	//Move vehicle to new position
	        	//Get engine consume for this round
	        	//Verify damage
	        	//Verify tank
        	}
        	repaint();
            try{
                Thread.sleep(Constants.threadDelay);
            }catch (InterruptedException e){
            	
            }
            //Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
        }
    }
    
    private boolean verifyInputs() {
    	//Loop all pressed keys
		boolean engineWorking = false,
				engineHorizontalWorking = false;
    	
		if(!paused){
	    	for(int keyCode : keyboardManager.getTyped()){
	    		switch (keyCode){
	    		case Constants.KEY_LEFT:
	    			engineWorking = true;
	    			engineHorizontalWorking = true;
	    			vehicle.applyEngineSpeed(Direction.LEFT);
	    			break;
	    		case Constants.KEY_RIGHT:
	    			engineWorking = true;
	    			engineHorizontalWorking = true;
	    			vehicle.applyEngineSpeed(Direction.RIGHT);
	    			break;
	    		case Constants.KEY_UP:
	    			engineWorking = true;
	    			vehicle.applyEngineSpeed(Direction.UP);
	    			break;
	    		}
	    	}
    	}
		
		return engineHorizontalWorking;
    }

    public void start()
    {
    	mouseManager = new MouseManager(this);
        addMouseListener(mouseManager);
        keyboardManager = new KeyboardManager(this);
        addKeyListener(keyboardManager);
        painter = new Painter(this);
        
        if(thread==null)
        {
            thread=new Thread(this);
            thread.start();
        }
    }
    
	public void registerKeyTyped(KeyEvent e) {
		switch (e.getKeyCode()){
		case Constants.P:
			paused = !paused;
			System.out.println("Pause status changed to "+paused);
			break;
		}
	}
	public void registerKeyReleased(KeyEvent e) {
		
	}

	public Planet getPlanet() {
		return planet;
	}

	public Player getPlayer() {
		return player;
	}
}